#!/usr/bin/env pytho      
# -*- coding: utf-8 -*-
# @Author  : junpeng_chen
# @Time    : 2023/7/27 8:41
# @File    : order_by_recognition
# @annotation    :
import re
from utils.log import logger


class OrderByRecognition:
    def __init__(self):
        pass

    def order_by(self, question: str, sel, having, measure):
        """
        order_by字段识别
        1. 一般limit字段不为空的都要进行排序操作
        2. 先对指标进行操作：对有关联操作的指标进行排序
        3. 当没有指标时，对时间维度进行操作：选取单位最小的（天、月、季度、年）
        :param question: 自然语言查询
        :param sel: select字段
        :param having: having字段
        :param measure: measure字段
        :return: order_by字段
        """
        try:
            order_by = []
            having_ids = [having_condition[0] for having_condition in having]

            # limit(前x的还没实现)
            limit_many_key_pattern = r"最大|最多|最好|最棒|最高|最厉害|最少|最小|最差|最低|排名最后|(排名前(\d+)|排名后(\d+)|前(\d+)|后(\d+)|(\d+)个|(\d+)名|top(\d+)|第(\d+))(?!(个|年|月|日|季))"
            m = re.search(limit_many_key_pattern, question)
            if m:
                limit_idx_tuple = m.span()
                measure_id = ""
                alias = ""
                min_distance = len(question)
                temp_sequence = "ASC"
                for id in measure:
                    name = [item['name'] for item in sel if item['id'] == id][0]
                    measure_idx = question.find(name)
                    if measure_idx != -1:
                        measure_tuple = (measure_idx, measure_idx + len(name))
                        distance = abs(limit_idx_tuple[0] - measure_tuple[1]) if measure_tuple[0] < limit_idx_tuple[
                            0] else abs(measure_tuple[0] - limit_idx_tuple[1])
                        if distance < min_distance:
                            min_distance = distance
                            alias = name
                            measure_id = id
                            span = set(list(question[limit_idx_tuple[0]:limit_idx_tuple[1]]))
                            ASC_literal = set(["少", "小", "差", "低", "后", "倒"])
                            if len(ASC_literal) > len(ASC_literal - span):
                                # 说明存在这些字眼
                                temp_sequence = "ASC"
                            else:
                                # 说明不存在这些字眼
                                temp_sequence = "DESC"

                order_by.append([measure_id, temp_sequence, "ROW", "NAME", alias])

            # 检查指标操作
            for id in measure:
                if id in having_ids:
                    index = having_ids.index(id)
                    opt = having[index][2]
                    sequence = "DESC" if opt in [">", ">=", "="] else "ASC"
                    alias = ""
                    for item in sel:
                        if item['id'] == id:
                            alias = item['name']
                    order_by.append([id, sequence, "ROW", "NAME", alias])

            # 检查时间维度操作
            if len(order_by) == 0:
                time_cmp = {'': 4, 'year': 3, 'quarter': 2, 'month': 1, 'day': 0}
                min_time = time_cmp['']
                id = ''
                alias = ''
                for index, col_head in enumerate(sel):
                    if 'timeLevel' in col_head.keys() and time_cmp[col_head['timeLevel']] < min_time:
                        min_time = time_cmp[col_head['timeLevel']]
                        id = col_head['id']
                        alias = col_head['name']
                order_by.append([id, "ASC", "COL", "NAME", alias])
            res = dict()
            res['order_by'] = order_by
            return res
        except Exception as err:
            logger.error("some errors happened in order_by[{}]: {}".format(type(err), str(err)))
            raise
